home *** CD-ROM | disk | FTP | other *** search
- /**
- * PULLMENU.C Sample creation of a simple pull-down menu
- * system.
- *
- * This program displays a menu bar across the top of the screen (the
- * "root" menu) which contains several items, each of which has an
- * associated vertical "pulldown" menu associated with it.
- *
- * The command line format is as follows:
- *
- * pullmenu
- *
- * The purpose of PULLMENU is to provide a working example of the
- * proper method of construction and use of a pulldown menu system.
- *
- * Version 6.00 (C)Copyright Blaise Computing Inc. 1989
- *
- **/
-
- #include <ctype.h>
- #include <stdio.h>
-
- #include <bkeybrd.h>
- #include <bkeys.h>
- #include <bmenu.h>
- #include <butil.h>
- #include <bscreens.h>
- #include <bvideo.h>
- #include <bmouse.h>
-
- /* Text color is intense white on blue. */
- #define MYTEXTATR (utnybbyt (SC_BLUE, SC_WHITE | INTENSITY))
-
- /* Color of highlight bar is black text on a white */
- /* background. */
- #define MYHILATR (utnybbyt (SC_WHITE, SC_BLACK))
-
- /* Color of "protected" items is green on blue. */
- #define MYPROATR (utnybbyt (SC_BLUE, SC_GREEN))
-
- /* Color of menu borders is cyan on black. */
- #define MYBORDATR (utnybbyt (SC_BLACK, SC_CYAN))
-
- /* Color of menu titles is the same as menu borders.*/
- #define MYTITATR MYBORDATR
-
- #define NUL '\0'
- #define TRUE 1
- #define FALSE 0
-
- /* Constants returned by pulldown menu functions. */
- #define MOVE_LEFT -1
- #define MOVE_RIGHT 1
- #define STAY_PUT 0
-
- /* Terminate-on-error macro. */
- #define exitBad() \
- { \
- mohide(MO_HIDE); \
- fprintf (stderr, \
- "pullmenu: died with b_wnerr = %d in line %d", \
- b_wnerr, __LINE__); \
- exit (b_wnerr); \
- }
-
- typedef struct /* PULL_ITEM: Describes one item in a */
- { /* pulldown menu. */
- int row; /* The row on which the item is located.*/
- char *pitem_text; /* The item's text. */
- char *pselection_keys; /* The keys which will select the item. */
- } PULL_ITEM;
-
- typedef struct /* ROOT_ITEM: Describes one item in the */
- { /* root menu. */
- int column; /* The item's column. */
- char *pitem_text; /* The item's text. */
- char *pselection_keys; /* The keys which will select the item. */
- int display_pulldown; /* Whether to display the item's */
- /* pulldown automatically. */
- } ROOT_ITEM;
-
- /* Constants describing the locations of the menu */
- /* items in the root menu. */
- #define ITEM_ONE_COL 1
- #define ITEM_TWO_COL 12
- #define ITEM_THREE_COL 22
- #define ITEM_FOUR_COL 27
-
-
- /* Item descriptors for the root menu. */
- ROOT_ITEM root_items[] =
- {
- {ITEM_ONE_COL, " Language ", "Ll", 0},
- {ITEM_TWO_COL, " Machine ", "Mm", 0},
- {ITEM_THREE_COL, " OS ", "Oo", 0},
- {ITEM_FOUR_COL, " Quit ", "Qq", 0}
- };
- int num_root_items = sizeof(root_items) / sizeof(root_items[0]);
-
-
- /* Item descriptors for the "Language" menu. */
- PULL_ITEM language_items[] =
- {
- {1, " C++ ", "Cc"},
- {2, " C ", "Cc"},
- {3, " Pascal ", "Pp"},
- {4, " FORTRAN 77 ", "Ff"},
- {5, " COBOL ", "Cc"},
- {6, " Logo ", "Ll"},
- {7, " Pilot ", "Pp"}
- };
- int num_language_items = sizeof(language_items) /
- sizeof(language_items[0]);
-
-
- /* Item descriptors for the "Machine" menu. */
- PULL_ITEM machine_items[] =
- {
- {1, " Cray 2 ", "Cc"},
- {2, " VAX 11/780 ", "Vv"},
- {3, " IBM PS/2 80 ", "Ii"},
- {4, " Apple //GS ", "Aa"},
- {5, " Sinclair ZX80 ", "Ss"}
- };
- int num_machine_items = sizeof(machine_items) /
- sizeof(machine_items[0]);
-
-
- /* Item descriptors for the "OS" menu. */
- PULL_ITEM os_items[] =
- {
- {1, " VMS ", "Vv"},
- {2, " UNIX 4.2 BSD ", "Uu"},
- {3, " OS/2 ", "Oo"},
- {4, " DOS 2.0 ", "Dd"},
- {5, " CP/M 80 ", "Cc"}
- };
- int num_os_items = sizeof(os_items) / sizeof(os_items[0]);
-
-
- /* Declare internal subroutines. */
- BMENU *create_menu(int, int, PULL_ITEM *, int);
- int read_pulldown(BMENU *, int, int, PULL_ITEM *, int, int);
-
-
- void main ()
- {
- int mode, columns, active_page;
- BMENU *proot;
- BMENU *planguage_menu;
- BMENU *pmachine_menu;
- BMENU *pos_menu;
- BORDER border;
- WHERE where;
- int ch, scan;
- int row, col;
- int showrow, showcol;
- int done = FALSE;
- ADAP_STATE adapter_state;
- PAGE_STATE page_state;
- int current_item;
- int ret_value;
- int read_root = 1;
- int error_code;
-
- /* First we make certain that we are in 80 column */
- /* text video mode. */
- scgetvid(&adapter_state);
-
- switch (adapter_state.mode)
- {
- case 2:
- case 3:
- case 7:
- break;
-
- default:
- fprintf (stderr, "Pullmenu: This demonstration works only "
- "in 80 column\n");
- fprintf (stderr, " text modes (modes 2, 3, and 7)\n");
- exit (1);
- }
-
- /* Save the image and cursor of the current page to */
- /* restore later. */
- scsavepg(&page_state);
-
- scpclr();
-
- /* Create the menu data structures. */
- proot = mncreate(1, 80, MYTEXTATR, MYHILATR, MYPROATR, 0);
- if (proot == NULL)
- exitBad()
-
- planguage_menu = create_menu(9, 12, language_items,
- num_language_items);
- if (planguage_menu == NULL)
- exitBad ()
-
- pmachine_menu = create_menu(7, 15, machine_items,
- num_machine_items);
- if (pmachine_menu == NULL)
- exitBad ()
-
- pos_menu = create_menu(7, 14, os_items, num_os_items);
- if (pos_menu == NULL)
- exitBad ()
-
- /* Highlight the first item in each of the pulldown */
- /* menus. */
- mnhilite(planguage_menu, language_items[0].row, 0, MN_HIGHLIGHT);
- mnhilite(pmachine_menu, machine_items[0].row, 0, MN_HIGHLIGHT);
- mnhilite(pos_menu, os_items[0].row, 0, MN_HIGHLIGHT);
-
- /* Disable ESC key. */
- if (mnkey (proot, 0, 0, KB_C_N_ESC, KB_S_N_ESC,
- MN_ABORT, MN_DELETE) == NULL)
- exitBad ()
-
- /* Set up items on the menu, and define */
- /* corresponding keys (upper and lower case of the */
- /* first letters of the items). */
- for (current_item = 0; current_item < num_root_items;
- current_item++)
- {
- if (mnitmkey(proot, 0, root_items[current_item].column, 0,
- root_items[current_item].pitem_text,
- root_items[current_item].pselection_keys, MN_TRANSMIT) ==
- NULL)
- {
- exitBad ()
- }
- }
-
- /* Figure out where to display the menu. */
- where.dev = scmode(&mode, &columns, &active_page);
- where.page = active_page;
- where.corner.row = 0;
- where.corner.col = 0;
-
- /* Specify no border. */
- border.type = BBRD_NO_BORDER;
-
- /* Display the menu on the screen. */
- if (mndsplay (proot, &where, &border) == NULL)
- exitBad ()
-
- /* Display a status bar at the bottom of the screen.*/
- viatrect(scrows() - 1, 0, scrows() - 1, 79, SC_WHITE | INTENSITY,
- SC_RED);
- vidspmsg(scrows() - 1, 0, -1, -1, "Current selection:");
-
- /* If the mouse is present, enable its cursor. */
- if (MO_OK == mohide(MO_SHOW))
- if (NULL == mnmstyle(proot, MN_MOU_CLICK, MO_LEFT))
- exitBad ()
-
- /* Set up starting item for highlight bar. */
- current_item = 0;
-
- do
- {
- /* Leave this menu on the screen until they select */
- /* the "Quit" entry. */
- row = 0;
- col = root_items[current_item].column;
-
- /* If read_root is non-zero, then we need to read a */
- /* user response from the root menu; otherwise */
- /* read a response from the pulldown associated */
- /* with the currently highlighted item. */
- if (read_root)
- {
- error_code = mnread (proot, row, col, &row, &col,
- &ch, &scan,
- MN_KEEP_HIGHLIGHT | MN_ALL_TRANSMIT);
- if (error_code == MN_READ_AB)
- {
- /* If the user aborted the menu, ignore it. */
- b_wnerr = WN_NO_ERROR;
- }
- else
- if (error_code)
- exitBad ()
-
-
- /* Find the index of the selected item. */
- for (current_item = 0; current_item < num_root_items;
- current_item++)
- {
- if (root_items[current_item].column == col)
- break;
- }
- }
-
- /* Set up location to show sub-menu. */
- showrow = where.corner.row + 2;
- showcol = where.corner.col + col;
-
- ret_value = STAY_PUT;
-
- /* If the user transmitted an item, display its */
- /* pulldown; if it was the "Quit" item, quit. */
- if (read_root &&
- ((ch == KB_C_N_ENTER) && (scan == KB_S_N_ENTER)) ||
- ((ch == 0xff) && (scan == 0xff) &&
- ((b_mnmoevent & MO_DCLICK) == MO_DCLICK)))
- {
- if (current_item == num_root_items - 1)
- done = TRUE;
- else
- root_items[current_item].display_pulldown = 1;
- }
-
- /* If the pulldown menu associated with this item */
- /* should be displayed, then display it and read a */
- /* user response from it. */
- if (root_items[current_item].display_pulldown)
- {
- /* Go do what was requested. */
- switch (col)
- {
- case ITEM_ONE_COL:
- ret_value = read_pulldown(planguage_menu,
- showrow, showcol,
- language_items,
- num_language_items, 20);
- break;
-
- case ITEM_TWO_COL:
- ret_value = read_pulldown(pmachine_menu,
- showrow, showcol,
- machine_items,
- num_machine_items, 32);
- break;
-
- case ITEM_THREE_COL:
- ret_value = read_pulldown(pos_menu,
- showrow, showcol,
- os_items,
- num_os_items, 47);
- break;
- }
- /* Assume that we're going to have to read a user */
- /* response from the main menu. */
- read_root = 1;
-
- /* If the key was a left or right arrow key, we */
- /* move the highlight bar the appropriate direction.*/
- if ((ret_value == MOVE_LEFT) || (ret_value == MOVE_RIGHT))
- {
- /* First, make sure this item's pulldown will be */
- /* displayed next time it is highlighted. */
- root_items[current_item].display_pulldown = 1;
-
- /* Now unhighlight the current item and determine */
- /* which item should be highlighted next. */
- mnhilite(proot, 0, root_items[current_item].column,
- MN_UNHIGHLIGHT);
-
- current_item = (current_item + ret_value +
- num_root_items) % num_root_items;
-
- /* Check to see if we need to read the root menu */
- /* next time around. */
- if (root_items[current_item].display_pulldown)
- {
- read_root = 0;
- mnhilite(proot, 0, root_items[current_item].column,
- MN_HIGHLIGHT);
- }
- }
- else
- root_items[current_item].display_pulldown = 0;
- }
-
- } while (!done);
-
- mndstroy(proot);
-
- /* Turn mouse cursor off. */
- mohide(MO_HIDE);
-
- /* Restore cursor position and style. */
- scsetvid(&adapter_state);
- screstpg(&page_state);
- }
-
-
- /**
- *
- * Name READ_PULLDOWN -- Display and allow user selection from
- * a pulldown menu.
- *
- * Synopsis ret_value = read_pulldown(pmenu, row, col,
- * pitems, num_items, msg_col);
- *
- * int ret_value The return value for the parent menu
- * to act on.
- * BMENU *pmenu The pulldown menu to read from.
- * int row, col Row and column where the upper
- * left corner of the menu's data
- * area should appear.
- * PULL_ITEM *pitems An array of item descriptors for
- * the menu.
- * int num_items The number of items in *pitems.
- * int msg_col The column at which to display a
- * message indicating which item was
- * selected.
- *
- *
- * Description This function displays pmenu and waits for user input.
- * If the user presses a left or right arrow key, it will
- * return MOVE_LEFT or MOVE_RIGHT to its caller, as
- * appropriate. An abort key or mouse event will cause
- * b_wnerr to be cleared, and the return code will be
- * STAY_PUT. A transmission key or mouse event causes
- * a return value of STAY_PUT.
- *
- * Returns ret_value MOVE_LEFT, MOVE_RIGHT, or STAY_PUT.
- *
- **/
-
-
- int read_pulldown(pmenu, row, col, pitems, num_items, msg_col)
- BMENU *pmenu;
- int row;
- int col;
- PULL_ITEM *pitems;
- int num_items;
- int msg_col;
- {
- int mode, columns, active_page;
- BORDER border;
- WHERE where;
- int ch, scan;
- int error_code;
-
- /* Figure out where to display the menu. */
- where.dev = scmode(&mode, &columns, &active_page);
- where.page = 0;
- where.corner.row = row;
- where.corner.col = col;
-
- /* Make a border with no title. */
- border.type = BBRD_SSSS;
- border.attr = MYBORDATR;
- border.ch = NUL;
-
- /* Display the menu on the screen. */
- if (mndsplay(pmenu, &where, &border) == NULL)
- exitBad ()
-
- /* Read a response from the menu. */
- error_code = mnread(pmenu, 1, 0, &row, &col, &ch, &scan,
- MN_KEEP_HIGHLIGHT | MN_REMOVE | MN_PREV_BAR);
-
- if (error_code == MN_READ_AB)
- {
- b_wnerr = WN_NO_ERROR;
- return(STAY_PUT);
- }
- if (error_code)
- exitBad ()
-
- /* Tell the caller whether a left or right arrow */
- /* key was hit. */
- if ((ch == KB_C_N_LEFT) && (scan == KB_S_N_LEFT))
- return(MOVE_LEFT);
-
- if ((ch == KB_C_N_RIGHT) && (scan == KB_S_N_RIGHT))
- return(MOVE_RIGHT);
-
- /* Display a message indicating which item was */
- /* selected. */
- if ((row - 1) < num_items)
- vidspmsg(scrows() - 1, msg_col, -1, -1,
- pitems[row -1].pitem_text);
-
- /* Tell the caller not to move left or right, and */
- /* not to call us immediately the next time our */
- /* root menu item is selected. */
- return(STAY_PUT);
- }
-
-
- /**
- *
- * Name CREATE_MENU -- Create a vertical menu given its
- * dimensions and an array of its items.
- *
- * Synopsis pmenu = create_menu(height, width, pitems, num_items);
- *
- * BMENU *pmenu Pointer to the newly created menu.
- * int height, The height and width of the menu to
- * width create.
- * PULL_ITEMS *pitems Array of pulldown menu item
- * descriptors.
- * int num_items Number of items in pitems.
- *
- * Description This function constructs a menu given its dimensions
- * and an array of item descriptors for its items. It
- * designates the left and right arrow keys to be
- * transmission keys, and disables the ESC key. It also
- * sets the window up to use the "click" style of mouse
- * events.
- *
- * Returns pmenu Pointer to the newly created menu, or NULL
- * if an error occurs.
- *
- **/
-
- BMENU *create_menu(height, width, pitems, num_items)
- int height;
- int width;
- PULL_ITEM *pitems;
- int num_items;
- {
- BMENU *pcreated;
- int current_item;
-
- pcreated = mncreate(height, width, MYTEXTATR, MYHILATR,
- MYPROATR, 0);
- if (pcreated == NULL)
- return(NULL);
-
- /* Change the left and right arrow keys. */
- if (mnkey(pcreated, 0, 0, KB_C_N_LEFT, KB_S_N_LEFT,
- MN_TRANSMIT, MN_CHANGE) == NULL)
- exitBad ()
- if (mnkey(pcreated, 0, 0, KB_C_N_RIGHT, KB_S_N_RIGHT,
- MN_TRANSMIT, MN_CHANGE) == NULL)
- exitBad ()
-
- /* Disable ESC key. */
- if (mnkey (pcreated, 0, 0, KB_C_N_ESC, KB_S_N_ESC,
- MN_ABORT, MN_DELETE) == NULL)
- exitBad ()
-
- /* Install mouse events. */
- if (NULL == mnmstyle(pcreated, MN_MOU_CLICK, MO_LEFT))
- exitBad ()
-
- /* Now install all the specified items. */
- for (current_item = 0; current_item < num_items; current_item++)
- {
- if (mnitmkey(pcreated, pitems[current_item].row, 0, 0,
- pitems[current_item].pitem_text,
- pitems[current_item].pselection_keys, MN_TRANSMIT) ==
- NULL)
- {
- exitBad ()
- }
- }
-
- return(pcreated);
- }